﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.CodeDom.Compiler;
using System.Linq.Expressions;
using System.Text.RegularExpressions;
using Microsoft.CSharp;

namespace ConsoleApp3
{
    internal class Program
    {

        public double test()
        {

            return 0;
                }

        
        static void Main(string[] args)
        {

            
            
            
         

          // string exp =
          //     "25.4*(0.54*[C])*(0.7*[Si]+1)*(3.333*[Mn]+1)*(2.16*[Cr]+1)*(0.363*[Ni]+1)*(3*[Mo]+1)*(0.365*[Cu]+1)*(1.73*[V]+1)*(2.5*[Zr]+1)";

          string exp = "double P4=7; double fc=0; if ([C]<=0.39) fc=[C]*0.54; else if ([C]<=0.55) fc= 0.171+0.001*[C]+0.265*Math.Pow([C],2); else if ([C]<=0.65) fc= 0.115+0.268*[C]-0.038*Math.Pow([C],2); else if ([C]<=0.75) fc= 0.143+0.2*[C]; else if ([C]<=0.9) fc= 0.062+0.409*[C]-0.135*Math.Pow([C],2); else fc=0; double fmn=0; if ([Mn]<=1.2) fmn=1+3.333*[Mn]; else if([Mn]<=1.95) fmn=-1.12+5.1*[Mn]; else fmn=0; double fsi=0; if([Si]<=2) fsi=1+0.7*[Si]; else fsi=0; double fni=0; if([Ni]<=1.5) fni=1+0.363*[Ni]; else if([Ni]<=3.5) fni=0.321+1.45*[Ni]-0.612*Math.Pow([Ni],2)+0.125*Math.Pow([Ni],3);  else fni=0; double fcr=0 ; if ([Cr]<=2.5) fcr=1+2.16*[Cr]; else fcr=0; double fmo=0; if([Mo]<=0.55) fmo=1+3*[Mo]; else fmo=0; double fcu=0; if([Cu]<=0.55) fcu=1+0.365*[Cu]; else fcu=0; double fv=0; if([V]<=0.2) fv=1+1.73*[V]; else fv=0; double fzr=0; if([Zr]<=0.25) fzr=1+2.5*[Zr] ; else fzr=0; double fgz=0; if(P4<=4) fgz=1.27; else if(P4<=5) fgz=1.172; else if(P4<=6) fgz=1.083; else if(P4<=7) fgz=1; else fgz=1-0.08*(P4-7);  double ac4=0; ac4=fmn*fsi*fni*fcr*fmo*fcu*fv*fzr*fgz ;  double ai4=0; if([C]<=0.85) ai4=13.121-101.16*[C]+383.76*Math.Pow([C],2)-729.9*Math.Pow([C],3)+675.13*Math.Pow([C],4)-242.44*Math.Pow([C],5);  else ai4=1; double aj4=0; if([C]<=0.81)aj4=10.318-70.135*[C]+248.92*Math.Pow([C],2)-454.75*Math.Pow([C],3)+411.02*Math.Pow([C],4)-146.47*Math.Pow([C],5);  else aj4=1; double ak4=0; if([C]<=0.77) ak4=10.542-80.631*[C]+320.36*Math.Pow([C],2)-653.01*Math.Pow([C],3)+655.52*Math.Pow([C],4)-257.51*Math.Pow([C],5);  else ak4=1; double al4=0; if([C]<=0.73) al4=9.034-64.879*[C]+252.92*Math.Pow([C],2)-515.53*Math.Pow([C],3)+522.33*Math.Pow([C],4)-208.46*Math.Pow([C],5);  else al4=1; double am4=0; if([C]<=0.67) am4=8.094-55.906*[C]+219.38*Math.Pow([C],2)-466.23*Math.Pow([C],3)+504.97*Math.Pow([C],4)-219.45*Math.Pow([C],5);  else am4=1; double an4=0; if([C]<=0.63) an4=9.048-77.438*[C]+362.81*Math.Pow([C],2)-895.73*Math.Pow([C],3)+1101.9*Math.Pow([C],4)-532.49*Math.Pow([C],5);  else an4=1; double ao4=0; if([C]<=0.59) ao4=6.921-48.238*[C]+207.29*Math.Pow([C],2)-507.17*Math.Pow([C],3)+644.04*Math.Pow([C],4)-328.39*Math.Pow([C],5);  else ao4=1; double ap4=0; if([C]<=0.55) ap4=7.24-55.334*[C]+254.54*Math.Pow([C],2)-655.33*Math.Pow([C],3)+867.43*Math.Pow([C],4)-459.59*Math.Pow([C],5);  else ap4=1; double aq4=0; if([C]<=0.53) aq4=7.116-56.58*[C]+273.62*Math.Pow([C],2)-740.01*Math.Pow([C],3)+1021.5*Math.Pow([C],4)-559.45*Math.Pow([C],5);  else aq4=1; double ah4=0; if(ac4<5) ah4=1; else if(ac4==5) ah4=ai4; else if(ac4<=7) ah4=ai4-(ai4-aj4)*(ac4-5)/2 ; else if(ac4<=9) ah4=aj4-(aj4-ak4)*(ac4-7)/2; else if(ac4<=11) ah4=ak4-(ak4-al4)*(ac4-9)/2 ; else if(ac4<=13) ah4=al4-(al4-am4)*(ac4-11)/2 ; else if(ac4<=15) ah4=am4-(am4-an4)*(ac4-13)/2; else ah4=1; double tmp=25.4*fc*fmn*fsi*fni*fcr*fmo*fcu*fv*fzr*fgz;  if([B]<0.001) return tmp; else { if (ac4<=15) return tmp*ah4; if(ac4<=18) return tmp*(an4-(an4-ao4)*(ac4-15)/3); if(ac4<=22) return tmp*(ao4-(ao4-ap4)*(ac4-18)/4); if (ac4<=26) return tmp*(ap4-(ap4-aq4)*(ac4-22)/4);  else return 0; }";     
                      
                         
                
                

           
            
            //正则获取元素
           var grps=  Regex.Matches(exp, "\\[\\w+\\]", RegexOptions.IgnoreCase);

           var lstElement = new List<string>();
           foreach (Match grp in grps )
           {
               if(!lstElement.Contains(grp.Value))
               lstElement.Add(grp.Value);
           }

           Dictionary<string, string> dic_ele = new Dictionary<string, string>();
           dic_ele.Add("[C]","0.36");
           dic_ele.Add("[Mn]","1.40");
           dic_ele.Add("[Si]","0.35");
           dic_ele.Add("[Ni]","0.20");
           dic_ele.Add("[Cr]","0.25");
           dic_ele.Add("[Mo]","0.10");
           dic_ele.Add("[Cu]","0.25");
           dic_ele.Add("[V]","0.10");
           dic_ele.Add("[Zr]","0.00");
          // dic_ele.Add("[P4]","7");
           dic_ele.Add("[B]","0.001");
           foreach (var ele in lstElement)
           {
               exp= exp.Replace(ele, dic_ele[ele]);
           }
            
           //
           ExpressionMethod e = new ExpressionMethod(exp);
            Console.WriteLine($"  FC :{e.Compute()}" );
            //Console.Read();
        }
    }



    
    //labmabda   ()=>{ return 1 };
    
    
    public class ExpressionMethod
    {
        object instance;
        MethodInfo method;
        /// <summary>
        /// 表达试运算
        /// </summary>
        /// <param name="expression">表达试</param>
        public ExpressionMethod(string expression)
        {
            if (expression.IndexOf("return") < 0) expression = "return " + expression + ";";
            string className = "Expression";
            string methodName = "Compute";
            CompilerParameters p = new CompilerParameters();
            p.GenerateInMemory = true;
            string source = $"using System;sealed class {className}{{public double {methodName}(){{{expression}}}}}";
            CompilerResults cr = new CSharpCodeProvider().CompileAssemblyFromSource(p,source);
            
          //  Console.WriteLine(source);
            if (cr.Errors.Count== 0)
            {   instance = cr.CompiledAssembly.CreateInstance(className);
                method = instance.GetType().GetMethod(methodName);
            
            }
            else
            {
                string msg = "Expression(\"" + expression + "\"): \n";
                foreach (CompilerError err in cr.Errors)
                { msg += err.ToString() + "\n"; }
                throw new Exception(msg);
            }
            
         
        }
        /// <summary>
        /// 处理数据
        /// </summary>
        /// <param name="x"></param>
        /// <returns>返回计算值</returns>
        public double Compute()
        {
            if (method != null) return (double)method.Invoke(instance, null);

            return 0;


        }
    }
}



 
